﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using EnvDTE;

namespace SPVisualDev
{
    internal class FeatureManager
    {
        private ProjectItem m_feature_folder;
        
        private XmlDocument m_feature_file;
        private int m_feature_file_init_xml_hash_code;

        private List<ElementInfo> m_elements_list = new List<ElementInfo>();
        private Dictionary<string, XmlDocument> m_element_files_list = new Dictionary<string, XmlDocument>();
        private Dictionary<string, int> m_elements_init_xml_hash_code = new Dictionary<string, int>();
        private int m_element_counter;
        private Guid m_feature_id;

        private List<Guid> m_activation_dep_list = new List<Guid>();


        public FeatureManager(ProjectItem FeatureFolder)
        {
            m_feature_folder = FeatureFolder;
        }

        public string FeatureID { get; set; }
        public string FeatureTitle { get; set; }
        public string FeatureDescription { get; set; }
        public string FeatureVersion { get; set; }
        public string FeatureScope { get; set; }
        public string FeatureDefaultResourceFile { get; set; }
        public bool? FeatureHidden { get; set; }
        public string FeatureEventReceiverAssembly { get; set; }
        public string FeatureEventReceiverClass { get; set; }

        public List<Guid> ActivationDependencies
        {
            get { return m_activation_dep_list; }
        }

        public List<ElementInfo> GetAllElements()
        {
            return m_elements_list;
        }

        public ElementInfo AddElement(string ElementFileName, string ElementXml)
        {
            ElementInfo el_info = new ElementInfo();

            el_info.New = true;
            el_info.ID = m_element_counter;
            m_element_counter++;

            if (string.IsNullOrEmpty(ElementFileName))
            {
                if (m_element_files_list.Count > 0)
                {
                    string[] arr = new string[m_element_files_list.Count];
                    m_element_files_list.Keys.CopyTo(arr, 0);
                    ElementFileName = arr[0];
                }
                else
                {
                    ElementFileName = "Elements.xml";
                }
            }

            if (m_element_files_list.ContainsKey(ElementFileName.ToLower()))
            {
                try
                {
                    el_info.ProjectItem = m_feature_folder.ProjectItems.Item(ElementFileName);
                }
                catch { }

                el_info.XmlDoc = m_element_files_list[ElementFileName.ToLower()];
            }
            else
            {
                XmlDocument xmldoc = new XmlDocument();
                xmldoc.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?>
<Elements xmlns=""http://schemas.microsoft.com/sharepoint/"">
</Elements>");

                m_element_files_list.Add(ElementFileName.ToLower(), xmldoc);

                el_info.XmlDoc = xmldoc;

                m_elements_init_xml_hash_code.Add(ElementFileName.ToLower(), xmldoc.OuterXml.GetHashCode());

            }


            el_info.ElementFileName = ElementFileName;

            XmlDocument xmldoc_temp = new XmlDocument();
            xmldoc_temp.LoadXml(ElementXml);

            el_info.ElementName = xmldoc_temp.DocumentElement.LocalName;
            el_info.XmlElementNode = el_info.XmlDoc.CreateElement(el_info.ElementName, Common.C_MS_SHAREPOINT_XMLNS);

            foreach (XmlAttribute attrib in xmldoc_temp.DocumentElement.Attributes)
            {
                el_info.XmlElementNode.SetAttribute(attrib.Name, attrib.Value);
            }

            el_info.XmlElementNode.InnerXml = xmldoc_temp.DocumentElement.InnerXml;
            el_info.XmlDoc.DocumentElement.AppendChild(el_info.XmlElementNode);

            m_elements_list.Add(el_info);

            return el_info;
        }

        public ElementInfo GetElement(int ElementID)
        {
            foreach (ElementInfo el_info in m_elements_list)
            {
                if (el_info.ID == ElementID)
                    return el_info;
            }

            throw new Exception("Element ID not found.");
        }

        public void RemoveElement(int ElementID, bool CommitChangesToFile)
        {
            ProjectItem item = null;
            XmlDocument xmldoc = null;

            int idx_to_remove = -1;
            for (int i = 0; i < m_elements_list.Count; i++)
            {
                if (ElementID == m_elements_list[i].ID)
                {
                    item = m_elements_list[i].ProjectItem;
                    xmldoc = m_elements_list[i].XmlDoc;

                    idx_to_remove = i;

                    break;
                }
            }

            if (idx_to_remove != -1)
            {
                XmlElement xel = m_elements_list[idx_to_remove].XmlElementNode;
                xel.ParentNode.RemoveChild(xel);

                m_elements_list.RemoveAt(idx_to_remove);
            }

            if (CommitChangesToFile && item != null && xmldoc != null)
            {
                //SCC handle
                if (Common.CheckOutItemFromSCC(item))
                {
                    Common.SaveXmlIndented(ref xmldoc, Common.GetProjectItemPath(item));
                }
            }

        }

        public void RemoveFeatureXMLElementFile(string LocationAttribute, bool UseWildcard)
        {
            List<XmlElement> elements_to_remove = new List<XmlElement>();

            foreach (XmlNode node in m_feature_file.GetElementsByTagName("ElementFile"))
            {
                XmlElement el = node as XmlElement;
                if (el == null)
                    continue;

                if (UseWildcard)
                {
                    if (el.GetAttribute("Location").ToLower().StartsWith(LocationAttribute.ToLower()))
                    {
                        if (!elements_to_remove.Contains(el))
                            elements_to_remove.Add(el);
                    }
                }
                else
                {
                    if (el.GetAttribute("Location").ToLower() == LocationAttribute.ToLower())
                    {
                        if (!elements_to_remove.Contains(el))
                            elements_to_remove.Add(el);
                    }
                }
            }

            foreach (XmlElement element in elements_to_remove)
            {
                element.ParentNode.RemoveChild(element);
            }
        }

        public void RemoveListEventRegistration(int ListType, bool CommitChangesToFile)
        {
            string list_type = ListType.ToString();

            foreach (string file in m_element_files_list.Keys)
            {
                XmlDocument xmldoc = m_element_files_list[file];
                List<XmlElement> elements_to_remove = new List<XmlElement>();

                foreach (XmlNode node in xmldoc.GetElementsByTagName("Receivers"))
                {
                    XmlElement element = node as XmlElement;
                    if (element == null)
                        continue;

                    if (element.GetAttribute("ListTemplateOwner") != "")
                    {
                        Guid g = Guid.Empty;
                        try
                        {
                            g = new Guid(element.GetAttribute("ListTemplateOwner"));
                        }
                        catch
                        {
                        }

                        if (g != Guid.Empty)
                        {
                            if (g != m_feature_id)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }

                    if (Common.GetXmlAttribute(element, "ListTemplateId") == list_type)
                    {
                        elements_to_remove.Add(element);
                    }
                }

                foreach (XmlElement element in elements_to_remove)
                {
                    element.ParentNode.RemoveChild(element);
                }

                if (CommitChangesToFile && elements_to_remove.Count > 0)
                {
                    //SCC handle
                    ProjectItem item = m_feature_folder.ProjectItems.Item(file);
                    if (Common.CheckOutItemFromSCC(item))
                    {
                        Common.SaveXmlIndented(ref xmldoc, Common.GetProjectItemPath(item));
                    }
                }

            }

        }

        public void ReadContent()
        {
            foreach (ProjectItem item in m_feature_folder.ProjectItems)
            {
                if (item.Kind != Constants.vsProjectItemKindPhysicalFile)
                    continue;

                if (Path.GetExtension(item.Name).ToLower() != ".xml")
                    continue;

                XmlDocument xmldoc = new XmlDocument();

                try
                {
                    xmldoc.Load(Common.GetProjectItemPath(item));
                }
                catch(XmlException ex)
                {
                    throw new XmlException("Error loading xml " + ex.SourceUri + ". " + ex.Message, ex.InnerException, ex.LineNumber, ex.LinePosition);
                }

                if (xmldoc.DocumentElement.LocalName != "Elements")
                    continue;


                foreach (XmlNode node in xmldoc.DocumentElement.ChildNodes)
                {
                    XmlElement element = node as XmlElement;
                    if (element == null)
                        continue;

                    ElementInfo el_info = new ElementInfo();
                    el_info.ID = m_element_counter;
                    el_info.ProjectItem = item;
                    el_info.XmlDoc = element.OwnerDocument;
                    el_info.XmlElementNode = element;
                    el_info.ElementName = element.LocalName;
                    el_info.ElementFileName = item.Name;
                    m_elements_list.Add(el_info);

                    m_element_counter++;
                }

                m_element_files_list.Add(item.Name.ToLower(), xmldoc);
                m_elements_init_xml_hash_code.Add(item.Name.ToLower(), xmldoc.OuterXml.GetHashCode());
            }

            ProjectItem feature_xml_item = null;
            try
            {
                feature_xml_item = m_feature_folder.ProjectItems.Item("Feature.xml");
            }
            catch
            {
                string temp_file_path = Path.GetTempPath() + "\\Feature.xml";

                if (File.Exists(temp_file_path))
                    File.Delete(temp_file_path);

                try
                {
                    using (StreamWriter writer = File.CreateText(temp_file_path))
                    {
                        writer.Write(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<Feature xmlns=""http://schemas.microsoft.com/sharepoint/"">
</Feature>");
                    }

                    m_feature_folder.ProjectItems.AddFromFileCopy(temp_file_path);

                    feature_xml_item = m_feature_folder.ProjectItems.Item("Feature.xml");
                }
                finally
                {
                    try
                    {
                        File.Delete(temp_file_path);
                    }
                    catch { }
                }
            }

            m_feature_file = new XmlDocument();
            try
            {
                m_feature_file.Load(Common.GetProjectItemPath(feature_xml_item));
            }
            catch(XmlException ex)
            {
                throw new XmlException("Error loading xml " + ex.SourceUri + ". " + ex.Message, ex.InnerException, ex.LineNumber, ex.LinePosition);
            }

            XmlNamespaceManager manager = new XmlNamespaceManager(m_feature_file.NameTable);
            manager.AddNamespace("sp", Common.C_MS_SHAREPOINT_XMLNS);

            this.FeatureID = Common.GetXmlAttribute(m_feature_file.DocumentElement, "ID");
            this.FeatureTitle = Common.GetXmlAttribute(m_feature_file.DocumentElement, "Title");
            this.FeatureDescription = Common.GetXmlAttribute(m_feature_file.DocumentElement, "Description");
            this.FeatureVersion = Common.GetXmlAttribute(m_feature_file.DocumentElement, "Version");
            this.FeatureScope = Common.GetXmlAttribute(m_feature_file.DocumentElement, "Scope");
            this.FeatureDefaultResourceFile = Common.GetXmlAttribute(m_feature_file.DocumentElement, "DefaultResourceFile");

            try
            {
                m_feature_id = new Guid(this.FeatureID);
            }
            catch
            {
            }

            string s = Common.GetXmlAttribute(m_feature_file.DocumentElement, "Hidden");
            if (!string.IsNullOrEmpty(s))
                this.FeatureHidden = bool.Parse(s);

            this.FeatureEventReceiverAssembly = Common.GetXmlAttribute(m_feature_file.DocumentElement, "ReceiverAssembly");
            this.FeatureEventReceiverClass = Common.GetXmlAttribute(m_feature_file.DocumentElement, "ReceiverClass");

            m_activation_dep_list = new List<Guid>();
            foreach(XmlNode node in m_feature_file.GetElementsByTagName("ActivationDependency"))
            {
                XmlElement xel = node as XmlElement;
                if (xel == null)
                    continue;

                Guid id;
                try
                {
                    id = new Guid(Common.GetXmlAttribute(xel, "FeatureId").ToUpper());
                }
                catch
                {
                    id = Guid.Empty;
                }

                m_activation_dep_list.Add(id);
            }


            m_feature_file_init_xml_hash_code = m_feature_file.OuterXml.GetHashCode();
        }

        public void WriteContent(bool ForceUpdate)
        {
            List<string> files_to_add = new List<string>();
            string skip_files = Common.GetUserSettingsKey(m_feature_folder.ContainingProject, "SkipFilesPushDown");

            GenerateEventReceivers();

            for (int i = 0; i < m_elements_list.Count; i++ )
            {
                ElementInfo el_info = m_elements_list[i];

                XmlNamespaceManager manager = new XmlNamespaceManager(el_info.XmlDoc.NameTable);
                manager.AddNamespace("sp", Common.C_MS_SHAREPOINT_XMLNS);

                if (el_info.ProjectItem == null)
                {
                    string file_name = el_info.ElementFileName;

                    try
                    {
                        el_info.ProjectItem = m_feature_folder.ProjectItems.Item(file_name);
                    }
                    catch { }

                    if (el_info.ProjectItem == null)
                    {
                        if (File.Exists(Common.GetProjectItemPath(m_feature_folder) + "\\" + file_name))
                        {
                            throw new Exception("File '" + file_name + "' already exists at '" + Common.GetProjectItemPath(m_feature_folder) + "'.");
                        }

                        string temp_file_path = Path.GetTempPath() + "\\" + file_name;

                        if (File.Exists(temp_file_path))
                            File.Delete(temp_file_path);

                        try
                        {
                            using (StreamWriter writer = File.CreateText(temp_file_path))
                            {
                                writer.Write(
    @"<?xml version=""1.0"" encoding=""utf-8""?>
<Elements xmlns=""http://schemas.microsoft.com/sharepoint/"">
</Elements>");
                            }

                            m_feature_folder.ProjectItems.AddFromFileCopy(temp_file_path);

                            el_info.ProjectItem = m_feature_folder.ProjectItems.Item(file_name);
                        }
                        finally
                        {
                            try
                            {
                                File.Delete(temp_file_path);
                            }
                            catch { }
                        }
                    }

                    if (!m_element_files_list.ContainsKey(file_name.ToLower()))
                    {
                        XmlDocument xmldoc = new XmlDocument();
                        xmldoc.Load(Common.GetProjectItemPath(el_info.ProjectItem));
                        m_element_files_list.Add(file_name.ToLower(), xmldoc);
                    }
                }

                if (el_info.ElementName == "Module")
                {
                    ProjectItem module_folder = null;
                    try
                    {
                        module_folder = m_feature_folder.ProjectItems.Item(el_info.XmlElementNode.GetAttribute("Path"));
                    }
                    catch { }

                    if (module_folder != null)
                    {
                        foreach (ProjectItem item in module_folder.ProjectItems)
                        {
                            if (Common.ShouldIgnoreFile(item.Name, skip_files))
                                continue;

                            XmlElement xel = el_info.XmlElementNode.SelectSingleNode("../sp:Module[@Path='" + module_folder.Name + "']/sp:File[@Url='" + item.Name + "']", manager) as XmlElement;
                            if (xel == null)
                            {
                                xel = el_info.XmlDoc.CreateElement("File", Common.C_MS_SHAREPOINT_XMLNS);
                                xel.SetAttribute("Url", item.Name);
                                xel.SetAttribute("Type", "GhostableInLibrary");
                                xel.SetAttribute("IgnoreIfAlreadyExists", "FALSE");
                                el_info.XmlElementNode.AppendChild(xel);

                                AddFeatureElementFile(module_folder.Name + "/" + item.Name);
                            }

                        }
                    }

                }

                else if (el_info.ElementName == "ListTemplate")
                {
                    ProjectItem list_template_folder = null;
                    try
                    {
                        list_template_folder = m_feature_folder.ProjectItems.Item(el_info.XmlElementNode.GetAttribute("Name"));
                    }
                    catch { }

                    if (list_template_folder != null)
                    {
                        foreach (ProjectItem item in list_template_folder.ProjectItems)
                        {
                            if (Common.ShouldIgnoreFile(item.Name, skip_files))
                                continue;

                            AddFeatureElementFile(list_template_folder.Name + "\\" + item.Name);
                        }
                    }
                }

            }

            foreach (KeyValuePair<string, XmlDocument> kvp in m_element_files_list)
            {
                ProjectItem item = null;
                try
                {
                    item = m_feature_folder.ProjectItems.Item(kvp.Key);
                }
                catch
                {
                    continue;
                }

                AddFeatureElementManifest(item.Name);

                XmlDocument xmldoc = kvp.Value;
                if (!ForceUpdate)
                {
                    if (xmldoc.OuterXml.GetHashCode() == m_elements_init_xml_hash_code[kvp.Key])
                        continue;
                }

                //SCC handle
                if (!Common.CheckOutItemFromSCC(item))
                    return;

                Common.SaveXmlIndented(ref xmldoc, Common.GetProjectItemPath(item));
            }


            //Feature file.

            Common.SetXmlAttribute(m_feature_file.DocumentElement, "Id", this.FeatureID, true);
            Common.SetXmlAttribute(m_feature_file.DocumentElement, "Title", this.FeatureTitle, true);
            Common.SetXmlAttribute(m_feature_file.DocumentElement, "Description", this.FeatureDescription, true);
            Common.SetXmlAttribute(m_feature_file.DocumentElement, "Version", this.FeatureVersion, true);
            Common.SetXmlAttribute(m_feature_file.DocumentElement, "Scope", this.FeatureScope, true);
            Common.SetXmlAttributeIgnoreIfValueMatches(m_feature_file.DocumentElement, "Hidden", this.FeatureHidden.ToString(), true);
            Common.SetXmlAttribute(m_feature_file.DocumentElement, "ReceiverAssembly", this.FeatureEventReceiverAssembly, true);
            Common.SetXmlAttribute(m_feature_file.DocumentElement, "ReceiverClass", this.FeatureEventReceiverClass, true);
            Common.SetXmlAttribute(m_feature_file.DocumentElement, "DefaultResourceFile", this.FeatureDefaultResourceFile, true);


            /*
            if (string.IsNullOrEmpty(this.FeatureEventReceiverAssembly))
                m_feature_file.DocumentElement.RemoveAttribute("ReceiverAssembly");

            if (string.IsNullOrEmpty(this.FeatureEventReceiverClass))
                m_feature_file.DocumentElement.RemoveAttribute("ReceiverClass");

            if (string.IsNullOrEmpty(this.FeatureDefaultResourceFile))
                m_feature_file.DocumentElement.RemoveAttribute("DefaultResourceFile");
            */

            ProjectItem resources_folder = null;
            try
            {
                resources_folder = m_feature_folder.ProjectItems.Item("Resources");
            }
            catch { }

            if (resources_folder != null)
            {
                foreach (ProjectItem item in resources_folder.ProjectItems)
                {
                    if (Common.ShouldIgnoreFile(item.Name, skip_files))
                        continue;

                    AddFeatureElementFile(resources_folder.Name + "\\" + item.Name);
                }
            }


            RefreshActivationDependencies();


            if (ForceUpdate || (m_feature_file_init_xml_hash_code != m_feature_file.OuterXml.GetHashCode()))
            {
                CommitChangesToFeatureXML();
            }

        }

        public void CommitChangesToFeatureXML()
        {
            //SCC handle
            ProjectItem feature_xml_item = m_feature_folder.ProjectItems.Item("Feature.xml");
            if (!Common.CheckOutItemFromSCC(feature_xml_item))
                return;

            Common.SaveXmlIndented(ref m_feature_file, Common.GetProjectItemPath(feature_xml_item));
        }

        private void RefreshActivationDependencies()
        {
            XmlNamespaceManager manager = new XmlNamespaceManager(m_feature_file.NameTable);
            manager.AddNamespace("sp", Common.C_MS_SHAREPOINT_XMLNS);

            List<XmlElement> elements_to_remove = new List<XmlElement>();

            foreach (XmlNode node in m_feature_file.SelectNodes("/sp:Feature/sp:ActivationDependencies/sp:ActivationDependency", manager))
            {
                XmlElement xel = node as XmlElement;
                if (xel == null)
                    continue;

                try
                {
                    Guid id = new Guid(Common.GetXmlAttribute(xel, "FeatureId").ToUpper());
                    if (!m_activation_dep_list.Contains(id))
                    {
                        elements_to_remove.Add(xel);
                    }
                }
                catch { }
            }

            foreach (XmlElement xel in elements_to_remove)
            {
                xel.ParentNode.RemoveChild(xel);
            }

            foreach (Guid activation_id in m_activation_dep_list)
            {
                bool found = false;

                foreach (XmlNode node in m_feature_file.SelectNodes("/sp:Feature/sp:ActivationDependencies/sp:ActivationDependency", manager))
                {
                    XmlElement xel = node as XmlElement;
                    if (xel == null)
                        continue;

                    try
                    {
                        Guid id = new Guid(Common.GetXmlAttribute(xel, "FeatureId").ToUpper());
                        if (id == activation_id)
                        {
                            found = true;
                            break;
                        }
                    }
                    catch { }
                }

                if (!found)
                {
                    XmlElement el_act_dep_root = m_feature_file.SelectSingleNode("/sp:Feature/sp:ActivationDependencies", manager) as XmlElement;
                    if (el_act_dep_root == null)
                    {
                        el_act_dep_root = m_feature_file.CreateElement("ActivationDependencies", Common.C_MS_SHAREPOINT_XMLNS);
                        m_feature_file.DocumentElement.AppendChild(el_act_dep_root);
                    }

                    XmlElement el_act_dep = m_feature_file.CreateElement("ActivationDependency", Common.C_MS_SHAREPOINT_XMLNS);
                    el_act_dep.SetAttribute("FeatureId", activation_id.ToString("D").ToUpper());

                    el_act_dep_root.AppendChild(el_act_dep);
                }

            }

        }

        private void AddFeatureElementFile(string Location)
        {
            XmlNamespaceManager manager = new XmlNamespaceManager(m_feature_file.NameTable);
            manager.AddNamespace("sp", Common.C_MS_SHAREPOINT_XMLNS);

            XmlNode element_manifests_node = m_feature_file.SelectSingleNode("/sp:Feature/sp:ElementManifests",manager);
            if (element_manifests_node == null)
            {
                element_manifests_node = m_feature_file.CreateElement("ElementManifests", Common.C_MS_SHAREPOINT_XMLNS);
                m_feature_file.DocumentElement.AppendChild(element_manifests_node);
            }

            bool found = false;
            foreach (XmlNode node in element_manifests_node.ChildNodes)
            {
                XmlElement element = node as XmlElement;
                if (element == null)
                    continue;

                if (Common.GetXmlAttribute(element, "Location").ToLower() == Location.ToLower())
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                XmlElement xel = m_feature_file.CreateElement("ElementFile", Common.C_MS_SHAREPOINT_XMLNS);
                xel.SetAttribute("Location", Location);
                element_manifests_node.AppendChild(xel);
            }
        }

        private void AddFeatureElementManifest(string ElementManifestName)
        {
            XmlNamespaceManager manager = new XmlNamespaceManager(m_feature_file.NameTable);
            manager.AddNamespace("sp", Common.C_MS_SHAREPOINT_XMLNS);

            XmlNode element_manifests_node = m_feature_file.SelectSingleNode("/sp:Feature/sp:ElementManifests", manager);
            if (element_manifests_node == null)
            {
                element_manifests_node = m_feature_file.CreateElement("ElementManifests", Common.C_MS_SHAREPOINT_XMLNS);
                m_feature_file.DocumentElement.AppendChild(element_manifests_node);
            }

            bool found = false;
            foreach (XmlNode node in element_manifests_node.ChildNodes)
            {
                XmlElement element = node as XmlElement;
                if (element == null)
                    continue;

                if (Common.GetXmlAttribute(element, "Location").ToLower() == ElementManifestName.ToLower())
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                XmlElement xel = m_feature_file.CreateElement("ElementManifest", Common.C_MS_SHAREPOINT_XMLNS);
                xel.SetAttribute("Location", ElementManifestName);
                element_manifests_node.AppendChild(xel);
            }

        }

        private void GenerateEventReceivers()
        {
            string[] arr = Common.RefreshEventReceivers(m_feature_file.OuterXml, MergeAllElementManifests(), Common.GetTargetPath(m_feature_folder.ContainingProject), m_feature_folder.Name, this.FeatureID);

            XmlDocument xmldoc = new XmlDocument();

            //First load the feature xml and extract receiver information.
            xmldoc.LoadXml(arr[0]);
            if (xmldoc.DocumentElement.GetAttribute("ReceiverAssembly") != "")
                m_feature_file.DocumentElement.SetAttribute("ReceiverAssembly", xmldoc.DocumentElement.GetAttribute("ReceiverAssembly"));
            if (xmldoc.DocumentElement.GetAttribute("ReceiverClass") != "")
                m_feature_file.DocumentElement.SetAttribute("ReceiverClass", xmldoc.DocumentElement.GetAttribute("ReceiverClass"));


            //Load the elements xml and extract receiver information.
            xmldoc.LoadXml(arr[1]);

            foreach (XmlNode node in xmldoc.DocumentElement.GetElementsByTagName("Receivers"))
            {
                XmlElement element = node as XmlElement;
                if (element == null)
                    continue;

                bool found = false;

                foreach (ElementInfo info in m_elements_list)
                {
                    if (info.ElementName == "Receivers")
                    {

                        string src_owner = info.XmlElementNode.GetAttribute("ListTemplateOwner");
                        string src_type = info.XmlElementNode.GetAttribute("ListTemplateId");

                        string dest_owner = element.GetAttribute("ListTemplateOwner");
                        string dest_type = element.GetAttribute("ListTemplateId");


                        if (string.Compare(src_owner, dest_owner, true) == 0 &&
                            string.Compare(src_type, dest_type, true) == 0)
                        {
                            info.XmlElementNode.InnerXml = element.InnerXml;
                            found = true;
                            break;
                        }
                    }
                    else if (info.ElementName == "ContentType")
                    {
                        
                    }
                }

                if (!found)
                {
                    AddElement("EventRegistrations.xml", element.OuterXml);
                }
            }

            foreach (XmlNode node in xmldoc.DocumentElement.GetElementsByTagName("ContentType"))
            {
                XmlElement element = node as XmlElement;
                if (element == null)
                    continue;

                foreach (ElementInfo info in m_elements_list)
                {
                    if (info.ElementName == "ContentType")
                    {
                        string src_id = Common.GetXmlAttribute(element, "ID");
                        string dest_id = Common.GetXmlAttribute(info.XmlElementNode, "ID");

                        if (string.Compare(src_id, dest_id, true) == 0)
                        {
                            info.XmlElementNode.InnerXml = element.InnerXml;
                            break;
                        }
                    }
                }
            }
        }

        private string MergeAllElementManifests()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(@"<?xml version=""1.0"" encoding=""utf-8""?>
<Elements xmlns=""http://schemas.microsoft.com/sharepoint/"">");

            foreach (KeyValuePair<string,XmlDocument> kvp in m_element_files_list)
            {
                sb.AppendLine(kvp.Value.DocumentElement.InnerXml);
            }

            sb.AppendLine("</Elements>");

            return sb.ToString();
        }
    }

    internal struct ElementInfo
    {
        public int ID { get; set; }
        public ProjectItem ProjectItem { get; set; }
        public string ElementFileName { get; set; }
        public string ElementName { get; set; }
        public XmlDocument XmlDoc { get; set; }
        public XmlElement XmlElementNode { get; set; }
        public bool New { get; set; }
        public string NewElementFileName { get; set; }

        public ElementInfo Clone()
        {
            ElementInfo el_info = new ElementInfo();
            el_info.ElementFileName = this.ElementFileName;
            el_info.ElementName = this.ElementName;
            el_info.ID = this.ID;
            el_info.New = this.New;
            el_info.NewElementFileName = this.NewElementFileName;
            el_info.ProjectItem = this.ProjectItem;
            el_info.XmlDoc = this.XmlDoc;
            el_info.XmlElementNode = this.XmlElementNode;

            return el_info;
        }
    }
}
